package com.example.demo.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.google.code.kaptcha.Constants;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.time.Duration;
import java.util.Properties;

//验证码相关
@Configuration
public class AppConfig {

    /**
     * @Qualifier 用于在自动注入时为对象创建别名，在使用Autowired时，会优先按照Qualifier配置得名称
     * @return
     */
    @Bean
    @Qualifier("producer")
    public DefaultKaptcha kaptcha(){
        DefaultKaptcha kaptcha = new DefaultKaptcha();
        Properties properties = new Properties();
        //验证码个数 4位数验证码
        properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_LENGTH,"4");
        //字体间隔
        properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_SPACE,"8");
        //干扰线颜色 目前不需要
        //干扰实现类
        properties.setProperty(Constants.KAPTCHA_NOISE_IMPL,"com.google.code.kaptcha.impl.NoNoise");
        //图片样式
        properties.setProperty(Constants.KAPTCHA_OBSCURIFICATOR_IMPL,
                "com.google.code.kaptcha.impl.WaterRipple");
        //文字来源
        properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_STRING,"0123456789");
        //引入配置
        Config config = new Config(properties);
        kaptcha.setConfig(config);
        return kaptcha;
    }

    /**
     * 新的分⻚插件
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }

    private RedisCacheConfiguration instanceConfig(Long ttl){
        //新建Json序列化对象
        Jackson2JsonRedisSerializer<Object> jackson2JonREdisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        //ObjectMapper
        ObjectMapper mapper = new ObjectMapper();
        //禁用日期序列化，例如原本日期2025-02-18 11:22:00 如果不使用下列方法，则会被转换成时间戳，
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        //日期的序列化及反序列化
        mapper.registerModule(new JavaTimeModule());
        //去掉各种@JsonSerialize注解的解析
        mapper.configure(MapperFeature.USE_ANNOTATIONS,false);
        //只针对非空的值进行序列化
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        //将类型序列化到属性json字符串中
        mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,
                ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        jackson2JonREdisSerializer.setObjectMapper(mapper);
        return RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(ttl))
//                .disableCachingNullValues()
                .serializeValuesWith(RedisSerializationContext.SerializationPair.

                        fromSerializer(jackson2JonREdisSerializer));
    }

    /**
     * 自定义在使用SpringCache时存储到redis中的key
     * @return
     */
    @Bean
    public KeyGenerator springCacheCustomKeyGenerator(){
        return new KeyGenerator() {
            @Override
            public Object generate(Object o, Method method, Object... objects) {
                String key = o.getClass().getSimpleName() + "_" + method.getName() +
                        "_" + StringUtils.arrayToDelimitedString(objects,"_");
                System.out.println(key);
                return key;
            }
        };
    }

    /**
     * Cache 缓存过期时间 3分钟
     * @param connectionFactory
     * @return
     */
    @Bean
    public RedisCacheManager cacheManagerMinute(RedisConnectionFactory connectionFactory){
        RedisCacheConfiguration config = instanceConfig(60L * 3);
        return RedisCacheManager.builder(connectionFactory)
                .cacheDefaults(config)
                .transactionAware()
                .build();
    }

    /**
     * Cache 缓存过期时间 1小时
     * @Primary 代表默认使用过期时间为1小时
     * @param connectionFactory
     * @return
     */
    @Bean
    @Primary
    public RedisCacheManager cacheManagerHour(RedisConnectionFactory connectionFactory){
        RedisCacheConfiguration config = instanceConfig(3600L);
        return RedisCacheManager.builder(connectionFactory)
                .cacheDefaults(config)
                .transactionAware()
                .build();
    }

    /**
     * Cache 缓存过期时间 1天
     * @param connectionFactory
     * @return
     */
    @Bean
    public RedisCacheManager cacheManagerDay(RedisConnectionFactory connectionFactory){
        RedisCacheConfiguration config = instanceConfig(3600L * 24);
        return RedisCacheManager.builder(connectionFactory)
                .cacheDefaults(config)
                .transactionAware()
                .build();
    }
}
